package org.javaboy.redis;

import java.io.*;
import java.net.Socket;

/**
 * 自定义 Redis 客户端
 * 1. 单行字符串以 + 开始，例如 +javaboy.org\r\n
 * 2. 多行字符串以 $ 开始，后面加上字符串长度，例如 $11\r\njavaboy.org\r\n
 * 3. 整数值以: 开始，例如 :1024\r\n
 * 4. 错误消息以 - 开始
 * 5. 数组以 * 开始，后面加上数组长度。
 * <p>
 * HTTP VS Socket
 */
public class RedisClient {

    Socket socket;

    public RedisClient() {
        try {
            socket = new Socket("centos.javaboy.org", 6379);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Redis 认证方法
     * auth password
     * [auth,password]
     *
     * @param password
     * @return
     */
    public String auth(String password) throws IOException {
        StringBuffer cmd = new StringBuffer();
        cmd
                //数组长度 [auth,password]
                .append("*2\r\n")
                // 字符串长度 auth
                .append("$4\r\n")
                // 字符串内容 auth
                .append("auth\r\n")
                // 字符串长度 password
                .append("$" + password.length() + "\r\n")
                .append(password)
                .append("\r\n");
//        System.out.println("auth cmd = " + cmd);
        //获取输出字符流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
        //通过 IO 流输出流，将字符串写出去
        bw.write(cmd.toString());
        //刷新缓冲区
        bw.flush();
        //注意，这里一定不要关闭 IO 流
        //如果想要获取到返回值，就去处理输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
        String s = br.readLine();
        //这里也注意，不要关闭流
        return s;
    }

    /**
     * [set,key,value]
     *
     * @param key
     * @param value
     * @return
     */
    public String set(String key, String value) throws IOException {
        StringBuffer cmd = new StringBuffer();
        cmd.append("*3\r\n")
                .append("$3\r\n")
                .append("set\r\n")
                .append("$" + key.length() + "\r\n")
                .append(key)
                .append("\r\n")
                .append("$" + value.length() + "\r\n")
                .append(value)
                .append("\r\n");
//        System.out.println("set cmd = " + cmd);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
        bw.write(cmd.toString());
        bw.flush();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
        return br.readLine();
    }

    /**
     * [get,key]
     *
     * @param key
     * @return
     * @throws IOException
     */
    public String get(String key) throws IOException {
        StringBuffer cmd = new StringBuffer();
        cmd.append("*2\r\n")
                .append("$3\r\n")
                .append("get\r\n")
                .append("$" + key.length() + "\r\n")
                .append(key)
                .append("\r\n");
//        System.out.println("get cmd = " + cmd);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
        bw.write(cmd.toString());
        bw.flush();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
        br.readLine();
        return br.readLine();
    }

    public void close() {
        try {
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
